package com.beauty.inventory.controller;

import com.beauty.inventory.dto.InventoryRequest;
import com.beauty.inventory.dto.InventoryResponse;
import com.beauty.inventory.exception.RateLimitExceededException;
import com.beauty.inventory.result.Result;
import com.beauty.inventory.service.InventoryService;
import com.beauty.inventory.service.RateLimiterService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/inventory")
@RequiredArgsConstructor
@Validated
@Slf4j
public class InventoryController {
    
    private final InventoryService inventoryService;
    private final RateLimiterService rateLimiterService;
    
    // 限流配置，每秒允许的请求数
    private static final double QUERY_RATE_LIMIT = 100.0;
    private static final double UPDATE_RATE_LIMIT = 50.0;
    
    @PostMapping
    public Result<InventoryResponse> createInventory(@Valid @RequestBody InventoryRequest inventoryRequest) {
        return Result.success(inventoryService.createInventory(inventoryRequest));
    }
    
    @GetMapping("/{id}")
    public Result<InventoryResponse> getInventoryById(@PathVariable Long id) {
        return Result.success(inventoryService.getInventoryById(id));
    }
    
    @GetMapping("/product/{productId}")
    public Result<InventoryResponse> getProductInventory(@PathVariable String productId) {
        log.info("【库存服务】接收到查询产品库存请求，产品ID: {}", productId);
        
        // 对查询操作进行限流
        String limiterKey = "query:" + productId;
        if (!rateLimiterService.tryAcquire(limiterKey, QUERY_RATE_LIMIT)) {
            log.warn("【库存服务】查询产品[{}]库存请求被限流", productId);
            throw new RateLimitExceededException("查询请求过于频繁，请稍后再试");
        }
        
        return Result.success(inventoryService.getProductInventory(productId));
    }
    
    @GetMapping("/warehouse/{warehouseId}")
    public Result<List<InventoryResponse>> getInventoriesByWarehouseId(@PathVariable String warehouseId) {
        return Result.success(inventoryService.getInventoriesByWarehouseId(warehouseId));
    }
    
    @GetMapping("/lowstock")
    public Result<List<InventoryResponse>> getLowStockItems() {
        return Result.success(inventoryService.getLowStockItems());
    }
    
    @GetMapping("/available")
    public Result<List<InventoryResponse>> getAvailableItems() {
        return Result.success(inventoryService.getAvailableItems());
    }
    
    @GetMapping
    public Result<List<InventoryResponse>> getAllInventories() {
        return Result.success(inventoryService.getAllInventories());
    }
    
    @PutMapping("/{id}")
    public Result<InventoryResponse> updateInventory(
            @PathVariable Long id, 
            @Valid @RequestBody InventoryRequest inventoryRequest) {
        return Result.success(inventoryService.updateInventory(id, inventoryRequest));
    }
    
    @DeleteMapping("/{id}")
    public Result<Void> deleteInventory(@PathVariable Long id) {
        inventoryService.deleteInventory(id);
        return Result.success();
    }
    
    @PutMapping("/product/{productId}/add")
    public Result<InventoryResponse> addStock(
            @PathVariable String productId,
            @RequestParam @Min(1) Integer quantity) {
        return Result.success(inventoryService.addStock(productId, quantity));
    }
    
    @PutMapping("/product/{productId}/reduce")
    public Result<InventoryResponse> reduceStock(
            @PathVariable String productId,
            @RequestParam Integer quantity) {
        log.info("【库存服务】接收到减少库存请求，产品ID: {}, 数量: {}", productId, quantity);
        
        // 对更新操作进行限流
        String limiterKey = "reduce:" + productId;
        if (!rateLimiterService.tryAcquire(limiterKey, UPDATE_RATE_LIMIT)) {
            log.warn("【库存服务】减少产品[{}]库存请求被限流", productId);
            throw new RateLimitExceededException("减少库存请求过于频繁，请稍后再试");
        }
        
        return Result.success(inventoryService.reduceStock(productId, quantity));
    }
    
    @PutMapping("/product/{productId}/reserve")
    public Result<InventoryResponse> reserveStock(
            @PathVariable String productId,
            @RequestParam Integer quantity) {
        log.info("【库存服务】接收到预留库存请求，产品ID: {}, 数量: {}", productId, quantity);
        
        // 对更新操作进行限流
        String limiterKey = "reserve:" + productId;
        if (!rateLimiterService.tryAcquire(limiterKey, UPDATE_RATE_LIMIT)) {
            log.warn("【库存服务】预留产品[{}]库存请求被限流", productId);
            throw new RateLimitExceededException("预留库存请求过于频繁，请稍后再试");
        }
        
        return Result.success(inventoryService.reserveStock(productId, quantity));
    }
    
    @PutMapping("/product/{productId}/release")
    public Result<InventoryResponse> releaseReservedStock(
            @PathVariable String productId,
            @RequestParam Integer quantity) {
        log.info("【库存服务】接收到释放预留库存请求，产品ID: {}, 数量: {}", productId, quantity);
        
        // 对更新操作进行限流
        String limiterKey = "release:" + productId;
        if (!rateLimiterService.tryAcquire(limiterKey, UPDATE_RATE_LIMIT)) {
            log.warn("【库存服务】释放产品[{}]预留库存请求被限流", productId);
            throw new RateLimitExceededException("释放库存请求过于频繁，请稍后再试");
        }
        
        return Result.success(inventoryService.releaseReservedStock(productId, quantity));
    }
    
    @PutMapping("/product/{productId}/increase")
    public Result<InventoryResponse> increaseStock(
            @PathVariable String productId,
            @RequestParam Integer quantity) {
        log.info("【库存服务】接收到增加库存请求，产品ID: {}, 数量: {}", productId, quantity);
        
        // 对更新操作进行限流
        String limiterKey = "increase:" + productId;
        if (!rateLimiterService.tryAcquire(limiterKey, UPDATE_RATE_LIMIT)) {
            log.warn("【库存服务】增加产品[{}]库存请求被限流", productId);
            throw new RateLimitExceededException("增加库存请求过于频繁，请稍后再试");
        }
        
        return Result.success(inventoryService.increaseStock(productId, quantity));
    }
    
    @GetMapping("/test-redisson")
    public Result<String> testRedisson() {
        log.info("【库存服务】测试Redisson功能");
        
        // 测试分布式锁
        String lockKey = "test:lock:key";
        try {
            rateLimiterService.tryAcquire("test-rate-limiter", 10.0);
            log.info("【库存服务】Redisson限流测试完成");
            
            return Result.success("Redisson测试成功，请查看日志输出");
        } catch (Exception e) {
            log.error("【库存服务】Redisson测试异常", e);
            return Result.error(500, "Redisson测试异常: " + e.getMessage());
        }
    }
} 